#pragma once
#include <cstdio>

class Logger {
public:
  virtual void logTransfer(long from, long to, double amount) const = 0;
};

class ConsoleLogger : public Logger {
public:
  ConsoleLogger() = default;
  ConsoleLogger(ConsoleLogger &&) = default;
  ConsoleLogger(const ConsoleLogger &) = default;
  ConsoleLogger &operator=(ConsoleLogger &&) = default;
  ConsoleLogger &operator=(const ConsoleLogger &) = default;
  ~ConsoleLogger() = default;

public:
  void logTransfer(long from, long to, double amount) const override {
    printf("[console] %ld -> %ld: %f\n", from, to, amount);
  }
};

class FileLogger : public Logger {
public:
  FileLogger() = default;
  FileLogger(FileLogger &&) = default;
  FileLogger(const FileLogger &) = default;
  FileLogger &operator=(FileLogger &&) = default;
  FileLogger &operator=(const FileLogger &) = default;
  ~FileLogger() = default;

public:
  void logTransfer(long from, long to, double amount) const override {
    // --snip--
    printf("[file] %ld -> %ld: %f\n", from, to, amount);
  }
};

class Bank {
  Logger *logger_ = nullptr;

public:
  Bank(Logger *logger) : logger_{logger} {}
  Bank(Bank &&) = default;
  Bank(const Bank &) = default;
  Bank &operator=(Bank &&) = default;
  Bank &operator=(const Bank &) = default;
  ~Bank() = default;

public:
  void setLogger(Logger *logger) { logger_ = logger; }
  void makeTransfer(long from, long to, double amount) {
    // --snip--
    if (logger_) {
      logger_->logTransfer(from, to, amount);
    }
  }
};
